import { Provide, Inject } from '@midwayjs/decorator';
import { JwtService } from '@midwayjs/jwt';
import { Context } from '@midwayjs/koa';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { UserEntity } from '../entity/user.entity';
import {
  FileUploadError,
  ResourceNotFound,
  FileFormatError,
} from '../error/custom.error';
import { v4 as uuid } from 'uuid';
import { writeFile, readFile, createReadStream } from 'fs';
import { UploadType } from '../interface/upload.interface';
import { checkEssentialParams } from '../utils';

@Provide()
export class UploadService {
  @Inject()
  jwt: JwtService;

  @Inject()
  ctx: Context;

  @InjectEntityModel(UserEntity)
  userModal: Repository<UserEntity>;

  // 获取资源
  async getResource(
    type: UploadType,
    filename: string,
    isDangerous: boolean = false
  ) {
    if (!isDangerous && filename.indexOf('/') !== -1) {
      throw new FileFormatError();
    }
    return createReadStream(`./upload/${type}/${filename}`);
  }

  // 上传文件 (相对安全)
  async uploadFile(
    type: UploadType,
    files: any,
    allowSuffix: string[],
    allowMime: string[]
  ) {
    checkEssentialParams(files);
    const [file] = files;
    // 判断文件名是否含有危险字符, 以及是否过大
    if (
      file.filename.indexOf('/') !== -1 ||
      file.filename.split('.').length > 2 ||
      file.size >= 10 * 1024 * 1024
    ) {
      throw new FileFormatError();
    }

    const suffix = file.filename.split('.')[1];
    const saveFilename = `${uuid()}.${suffix}`;

    // 对文件后缀和mimeType进行拦截
    if (!allowSuffix.includes(suffix) || !allowMime.includes(file.mimeType)) {
      throw new FileUploadError();
    }

    // 读取保存文件
    await new Promise(resolve => {
      readFile(file.data, (err, data) => {
        if (err) {
          throw new ResourceNotFound();
        } else {
          writeFile(`./upload/${type}/${saveFilename}`, data, () => {
            resolve('');
          });
        }
      });
    });
    // 返回保存的url
    return {
      filename: saveFilename,
      url: `/${type}/${saveFilename}`,
    };
  }

  // 上传文件 (危险)
  async uploadFileDangerously(files: any) {
    checkEssentialParams(files);
    const [file] = files;
    const suffix = file.filename.split('.')[1];

    // 判断文件类型是否符合
    if (!['jpg', 'jpeg', 'png'].includes(suffix)) {
      throw new FileFormatError();
    }

    // 读取保存文件
    await new Promise(resolve => {
      readFile(file.data, (err, data) => {
        if (err) {
          throw new ResourceNotFound();
        } else {
          writeFile(`./upload/${file.filename}`, data, () => {
            resolve('');
          });
        }
      });
    });

    return {
      filename: file.filename,
    };
  }
}
